package com.hnd.springframework.beans.factory.support.xml;

import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.XmlUtil;
import com.hnd.springframework.beans.BeansException;
import com.hnd.springframework.beans.PropertyValue;
import com.hnd.springframework.beans.PropertyValues;
import com.hnd.springframework.beans.factory.config.BeanDefinition;
import com.hnd.springframework.beans.factory.config.BeanReference;
import com.hnd.springframework.beans.factory.support.AbstractBeanDefinitionReader;
import com.hnd.springframework.beans.factory.support.BeanDefinitionRegistry;
import com.hnd.springframework.core.io.Resource;
import com.hnd.springframework.core.io.ResourceLoader;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import java.io.IOException;
import java.io.InputStream;

/**
 * @author hnd
 * 负责解析xml 文档 获取bean实例
 */
public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {

    public XmlBeanDefinitionReader(BeanDefinitionRegistry registry) {
        super(registry);
    }

    public XmlBeanDefinitionReader(ResourceLoader resourceLoader, BeanDefinitionRegistry registry) {
        super(resourceLoader, registry);
    }

    @Override
    public void LoadBeanDefinitions(Resource resource) throws BeansException {
        try {
            InputStream inputStream = resource.getInputStream();
            doLoadBeanDefinitions(inputStream);
        } catch (ClassNotFoundException | IOException e) {
            throw new BeansException("注册失败", e);
        }
    }


    @Override
    public void loadBeanDefinitions(Resource... resources) throws BeansException {
        for (Resource resource : resources) {
            LoadBeanDefinitions(resource);
        }

    }

    @Override
    public void loadBeanDefinitions(String location)throws BeansException  {
        ResourceLoader resourceLoader = getResourceLoader();
        Resource resource = resourceLoader.getResource(location);
        LoadBeanDefinitions(resource);
    }

    private void doLoadBeanDefinitions(InputStream  inputStream) throws ClassNotFoundException {
        Document document = XmlUtil.readXML(inputStream);
        Element root = document.getDocumentElement();

        NodeList childNodes = root.getChildNodes();
        for (int i = 0; i < childNodes.getLength(); i++) {
            Node item = childNodes.item(i);
            if (!(item instanceof Element)) {
                continue;
            }
            if (!"bean".equals(item.getNodeName())) {
                continue;
            }
            //注册bean
            Element element = (Element) item;
            String name = element.getAttribute("name");
            String clazzName = element.getAttribute("class");
            Class<?> clazz = Class.forName(clazzName);


            NodeList childNodesProperties = element.getChildNodes();
            PropertyValues propertyValues = new PropertyValues();
            for (int j = 0; j < childNodesProperties.getLength(); j++) {
                Node property = childNodesProperties.item(j);
                if (!(property instanceof Element)) {
                    continue;
                }
                if (!"property".equals(property.getNodeName())) {
                    continue;
                }
                Element propertyElement = (Element) property;
                //注入属性
                String attrName = propertyElement.getAttribute("name");
                String attrValue = propertyElement.getAttribute("value");
                String attrRef = propertyElement.getAttribute("ref");
                Object value = StrUtil.isNotEmpty(attrRef) ? new BeanReference(attrRef) : attrValue;

                propertyValues.addPropertyValue(new PropertyValue(attrName, value));
            }
            getRegistry().registryBeanDefinition(name, new BeanDefinition(name,clazz,BeanDefinition.SINGLETON,propertyValues));
        }

    }
}
